package me.seu.demo.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.mapping.*;
import co.elastic.clients.elasticsearch._types.query_dsl.*;
import co.elastic.clients.elasticsearch.core.IndexResponse;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Highlight;
import co.elastic.clients.elasticsearch.core.search.HighlightField;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import co.elastic.clients.elasticsearch.indices.IndexSettings;
import me.seu.demo.common.CommonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 91989
 * @title: EsTestController
 * @projectName xy-reader
 * @description: TODO
 * @date 2022/7/1 16:42
 */
@SuppressWarnings("rawtypes")
@RestController
@RequestMapping("/es")
public class EsTestController {

    @Resource(name = "coElasticsearchClient")
    private ElasticsearchClient client;


    @PostMapping("/createIndex")
    public CommonResult createIndex(String indexName) throws IOException {
        //定义索引的别名
        String KEYWORD = "";
        String indexAliasName = indexName + "_alias";
        Map<String, Property> propertyMap = new HashMap<>();
        //构建索引类型
        propertyMap.put("content_id", new Property(new IntegerNumberProperty.Builder().index(true).build()));
        propertyMap.put("content", new Property(new TextProperty.Builder().index(true).analyzer("standard").build()));
        propertyMap.put("content_en", new Property(new TextProperty.Builder().index(true).analyzer("standard").build()));
        propertyMap.put("create_time", new Property(new DateProperty.Builder().index(true).build()));
        //构建设置
        TypeMapping mapping = new TypeMapping.Builder().properties(propertyMap).build();
        IndexSettings indexSettings = new IndexSettings.Builder().numberOfShards(String.valueOf(1)).numberOfReplicas(String.valueOf(0)).build();
        CreateIndexRequest createIndexRequest = new CreateIndexRequest.Builder()
                .index("ik_test_index")
                .mappings(mapping)
                .settings(indexSettings)
                .build();
        //执行创建索引操作并返回结果
        CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest);
        return CommonResult.success();
    }

    /**
     * 　　* @description: 插入文档
     * 　　* @author Lin
     * 　　* @date 2022/7/5 17:26
     */
    @PostMapping("/insertDoc")
    public CommonResult insertDoc(String doc, String docEn) throws IOException {
        String indexName = "ik_test_index";
        Map<String, Object> paramMap = new HashMap<>();
        int[] randomInt = NumberUtil.generateRandomNumber(1, 10000, 1);
        paramMap.put("content_id", randomInt[0]);
        paramMap.put("content", doc);
        paramMap.put("content_en", docEn);
        paramMap.put("create_time", DateUtil.date());

        //插入文档
        IndexResponse response = client.index(i -> i.index(indexName).document(paramMap));

        return CommonResult.success(response);
    }

    /**
     * 　　* @description: 基于索引数据的多维度查询
     * 　　* @author Lin
     * 　　* @date 2022/7/7 9:56
     */
    @GetMapping("/getEs")
    public CommonResult getEs(String keyword) throws IOException {
        String str = "li";

        //分词查询构造器
        MatchQuery matchQuery = QueryBuilders.match().field("content_en").query(keyword).build();
        //布尔查询构造器
        BoolQuery.Builder queryBuilders = QueryBuilders.bool();
        queryBuilders.must(matchQuery._toQuery());
        //模糊匹配查询构造器 类似like查询
        WildcardQuery.Builder wildBuilder = QueryBuilders.wildcard();
        str = StrUtil.addSuffixIfNot(str, "*");
        WildcardQuery wildcardQuery = wildBuilder.field("name").wildcard(str).build();
        //精确匹配查询构造器
        TermQuery.Builder termBuilder = QueryBuilders.term();
        TermQuery termQuery = termBuilder.field("content_id").value("name").build();
        //布尔查询增加and条件
        queryBuilders.must(termQuery._toQuery());
        //构建出布尔查询
        BoolQuery boolQuery = queryBuilders.build();
        //高亮查询
        HighlightField.Builder highlightFieldBuilder = new HighlightField.Builder();
        HighlightField highlightField = highlightFieldBuilder.build();
        //构建高亮字段
        Highlight.Builder highlightBuilder = new Highlight.Builder();
        Highlight highlight = highlightBuilder.fields("content_en", highlightField).build();


        SearchRequest searchRequest = new SearchRequest.Builder().query(matchQuery._toQuery()).highlight(highlight).index("ik_test_index").build();
        /*SearchRequest searchRequest = new SearchRequest.Builder().index("new_index").build();*/
        /* SearchResponse search = client.search(s -> s.index("new_index").
                query(q -> q.match(m -> m.field("name").query(r->r.stringValue("li")))),
                Map.class);*/
        SearchResponse searchResponse = client.search(searchRequest, Map.class);
        //命中list
        List<Hit> list = searchResponse.hits().hits();
        //处理结果list
        List<Map<String, Object>> resList = new ArrayList<>();
        for (Hit hit : list) {
            Map<String, Object> resMap = new HashMap<>();
            Map highLight = hit.highlight();
            Double score = hit.score();
            Map map = (Map) hit.source();
            resMap.put("highLight", highLight);
            resMap.put("score", score);
            resMap.put("source", map);
            resList.add(resMap);
        }
        return CommonResult.success(resList);
    }


}

